package com.joker.aigc.tools.service.video.impl;

import com.joker.aigc.tools.service.video.MinioService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.UploadObjectArgs;
import io.minio.http.Method;
import io.minio.RemoveObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.UUID;

/**
 * MinIO服务实现类
 *
 * @author system
 * @date 2023-12-01
 */
@Slf4j
@Service
public class MinioServiceImpl implements MinioService {

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.access-key}")
    private String accessKey;

    @Value("${minio.secret-key}")
    private String secretKey;

    @Value("${minio.bucket-name.video:video-storage}")
    private String videoBucketName;

    @Value("${minio.bucket-name.thumbnail:thumbnail-storage}")
    private String thumbnailBucketName;

    private MinioClient minioClient;

    @PostConstruct
    public void init() {
        minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }

    public String uploadFile(File file, String bucketName, String objectName) {
        try {
            // 计算下耗时
            long startTime = System.currentTimeMillis();
            log.info("开始上传文件: {}", file.getName());
            // 获取文件类型
            String contentType = Files.probeContentType(file.toPath());
            if (contentType == null) {
                contentType = "application/octet-stream";
            }
            // 使用临时包装文件监控进度
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .filename(file.getAbsolutePath())
                            .contentType(contentType)
                            .build());
            long endTime = System.currentTimeMillis();
            log.info("上传文件完成: {} 耗时: {}s", file.getName(), (endTime - startTime)/1000);
            return getFileUrl(bucketName, objectName);
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public String uploadFile(MultipartFile file, String bucketName, String objectName) {
        try {
            InputStream inputStream = file.getInputStream();
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(inputStream, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
            return getFileUrl(bucketName, objectName);
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public String uploadVideo(MultipartFile videoFile) {
        String fileName = generateFileName(videoFile.getOriginalFilename());
        return uploadFile(videoFile, thumbnailBucketName, "videos/" + fileName);
    }

    @Override
    public String uploadVideo(File videoFile) {
        String fileName = generateFileName(videoFile.getName());
        return uploadFile(videoFile, videoBucketName, "videos/" + fileName);
    }

    @Override
    public String uploadThumbnail(MultipartFile thumbnailFile) {
        String fileName = generateFileName(thumbnailFile.getOriginalFilename());
        return uploadFile(thumbnailFile, thumbnailBucketName, "thumbnails/" + fileName);
    }

    @Override
    public String getFileUrl(String bucketName, String objectName) {
        try {
            return minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
        } catch (Exception e) {
            log.error("获取文件URL失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取文件URL失败: " + e.getMessage());
        }
    }

    @Override
    public void deleteFile(String bucketName, String objectName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build()
            );
        } catch (Exception e) {
            log.error("删除文件失败: {}", e.getMessage(), e);
            throw new RuntimeException("删除文件失败: " + e.getMessage());
        }
    }

    /**
     * 生成唯一文件名
     *
     * @param originalFilename 原始文件名
     * @return 唯一文件名
     */
    private String generateFileName(String originalFilename) {
        String extension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        return UUID.randomUUID().toString() + extension;
    }
}